import pygame
import random
import os
import copy

# 初始化Pygame
pygame.init()

# 游戏窗口设置
SCREEN_WIDTH = 460
SCREEN_HEIGHT = 720
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("羊了个羊")

# 颜色定义
BG_COLOR = (255, 255, 255)
BUTTON_COLOR = (100, 100, 255)
BUTTON_HOVER_COLOR = (150, 150, 255)
TEXT_COLOR = (255, 255, 255)

# 卡片尺寸和间距
CARD_WIDTH = 55
CARD_HEIGHT = 70
SPACING = 40

# 游戏区域布局
GRID_ROWS = 3
GRID_COLS = 3
grid_width = GRID_COLS * (CARD_WIDTH + SPACING) - SPACING
GRID_LEFT = (SCREEN_WIDTH - grid_width) // 2
GRID_TOP = 100

# 槽位区域设置
SLOT_ROWS = 1
SLOT_COLS = 7  # 最多存放7个卡片
slot_width = SLOT_COLS * (CARD_WIDTH + 5) - 5
SLOT_LEFT = (SCREEN_WIDTH - slot_width) // 2
SLOT_TOP = SCREEN_HEIGHT - CARD_HEIGHT - 50
SLOT_HEIGHT = CARD_HEIGHT + 20

# 道具设置
ITEM_WIDTH = 40
ITEM_HEIGHT = 60
ITEM_LEFT = SCREEN_WIDTH - ITEM_WIDTH - 390
ITEM_TOP = 60
item_count = 1

# 新增：撤销功能相关
UNDO_WIDTH = 40
UNDO_HEIGHT = 40
UNDO_LEFT = SCREEN_WIDTH - UNDO_WIDTH - 330
UNDO_TOP = 60
undo_count = 3  # 初始3次撤销机会

# 新增：洗牌功能相关
SHUFFLE_WIDTH = 40
SHUFFLE_HEIGHT = 40
SHUFFLE_LEFT = SCREEN_WIDTH - SHUFFLE_WIDTH - 270
SHUFFLE_TOP = 60
shuffle_count = 2  # 初始2次洗牌机会

# 新增：重新开始按钮设置
RESTART_WIDTH = 120
RESTART_HEIGHT = 40
RESTART_LEFT = (SCREEN_WIDTH - RESTART_WIDTH) // 2
RESTART_TOP = SCREEN_HEIGHT // 2 + 50

# 加载背景图像
try:
    # 修复：使用os.path.dirname(__file__)获取当前脚本所在目录，然后直接拼接image目录
    image_folder = os.path.join(os.path.dirname(__file__), "image")
    print(f"图像文件夹路径: {image_folder}")  # 添加这行用于调试

    background_path1 = os.path.join(image_folder, "back.png")
    background_path2 = os.path.join(image_folder, "back1.png")
    background_img1 = pygame.image.load(background_path1)
    background_img1 = pygame.transform.scale(background_img1, (SCREEN_WIDTH, SCREEN_HEIGHT))
    background_img2 = pygame.image.load(background_path2)
    background_img2 = pygame.transform.scale(background_img2, (SCREEN_WIDTH, SCREEN_HEIGHT))
    print("主背景图像加载成功")
    # 用于切换背景的标志
    current_background = 0
    # 背景切换的时间间隔（毫秒）
    BACKGROUND_SWITCH_INTERVAL = 200
except Exception as e:
    print(f"主背景图像加载失败: {e}")
    background_img1 = None
    background_img2 = None
    current_background = 0
    BACKGROUND_SWITCH_INTERVAL = 200

# 初始化背景切换时间（移到这里，确保一定会被定义）
last_switch_time = pygame.time.get_ticks()

# 加载槽位背景图像
try:
    slot_bg_path = os.path.join(image_folder, "back2.png")
    slot_bg_img = pygame.image.load(slot_bg_path)
    slot_bg_img = pygame.transform.scale(slot_bg_img, (slot_width + 20, SLOT_HEIGHT + 20))
    print("槽位背景图像加载成功")
except Exception as e:
    print(f"槽位背景图像加载失败: {e}")
    slot_bg_img = None

# 无论如何都定义COLORS，确保程序可以运行
COLORS = [
    (255, 0, 0),  # 红
    (0, 255, 0),  # 绿
    (0, 0, 255),  # 蓝
    (255, 255, 0),  # 黄
    (128, 0, 128),  # 紫
]

# 加载卡片图片
card_images = []
try:
    for i in range(5):
        if i == 0:
            tile_path = os.path.join(image_folder, "tile.png")
        else:
            tile_path = os.path.join(image_folder, f"tile{i}.png")

        print(f"尝试加载卡片图片: {tile_path}")  # 添加这行用于调试

        if os.path.exists(tile_path):
            img = pygame.image.load(tile_path)
            img = pygame.transform.scale(img, (CARD_WIDTH, CARD_HEIGHT))
            card_images.append(img)
            print(f"卡片图片 {os.path.basename(tile_path)} 加载成功")
        else:
            print(f"卡片图片 {tile_path} 不存在")

    if not card_images:
        print("没有找到任何卡片图片，将使用默认颜色")

except Exception as e:
    print(f"卡片图片加载失败: {e}")
    print("将使用默认颜色")

# 加载mask图像
try:
    mask_path = os.path.join(image_folder, "mask.png")
    print(f"尝试加载mask图像: {mask_path}")  # 添加这行用于调试

    mask_img = pygame.image.load(mask_path)
    mask_img = pygame.transform.scale(mask_img, (CARD_WIDTH, CARD_HEIGHT))
    print("mask图像加载成功")
except Exception as e:
    print(f"mask图像加载失败: {e}")
    mask_img = None

# 加载道具图像
try:
    item_path = os.path.join(image_folder, "xiaochu.webp")
    print(f"尝试加载道具图像: {item_path}")  # 添加这行用于调试

    item_img = pygame.image.load(item_path)
    item_img = pygame.transform.scale(item_img, (ITEM_WIDTH, ITEM_HEIGHT))
    print("道具图像加载成功")
except Exception as e:
    print(f"道具图像加载失败: {e}")
    item_img = None

# 新增：加载撤销按钮图像
try:
    undo_path = os.path.join(image_folder, "undo.webp")
    print(f"尝试加载撤销按钮图像: {undo_path}")  # 添加这行用于调试

    undo_img = pygame.image.load(undo_path)
    undo_img = pygame.transform.scale(undo_img, (UNDO_WIDTH, UNDO_HEIGHT))
    print("撤销按钮图像加载成功")
except Exception as e:
    print(f"撤销按钮图像加载失败: {e}")
    undo_img = None

# 新增：加载洗牌按钮图像
try:
    shuffle_path = os.path.join(image_folder, "sj.webp")
    print(f"尝试加载洗牌按钮图像: {shuffle_path}")  # 添加这行用于调试

    shuffle_img = pygame.image.load(shuffle_path)
    shuffle_img = pygame.transform.scale(shuffle_img, (SHUFFLE_WIDTH, SHUFFLE_HEIGHT))
    print("洗牌按钮图像加载成功")
except Exception as e:
    print(f"洗牌按钮图像加载失败: {e}")
    shuffle_img = None

# 粒子效果相关
PARTICLE_COLORS = [
    (255, 255, 255),  # 白色
    (255, 255, 0),  # 黄色
    (255, 165, 0),  # 橙色
    (255, 192, 203),  # 粉色
    (255, 0, 0),  # 红色
]


class Particle:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = random.randint(2, 6)
        self.color = random.choice(PARTICLE_COLORS)
        self.speed_x = random.uniform(-4, 4)
        self.speed_y = random.uniform(-6, -1)  # 向上发射为主
        self.gravity = 0.1
        self.life = random.randint(20, 40)  # 粒子生命周期

    def update(self):
        self.x += self.speed_x
        self.y += self.speed_y
        self.speed_y += self.gravity
        self.life -= 1
        return self.life > 0

    def draw(self):
        # 绘制粒子
        pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
        # 添加光晕效果
        glow_radius = self.radius + 2
        glow_surf = pygame.Surface((glow_radius * 2, glow_radius * 2), pygame.SRCALPHA)
        pygame.draw.circle(glow_surf, (*self.color, 100), (glow_radius, glow_radius), glow_radius)
        screen.blit(glow_surf, (int(self.x) - glow_radius, int(self.y) - glow_radius), special_flags=pygame.BLEND_ADD)


# 游戏状态
slots = []
score = 0
game_over = False
game_won = False
moving_cards = []
particles = []  # 存储所有粒子

# 新增：历史记录栈，用于撤销功能
history_stack = []


# 新增：重新开始游戏函数
def restart_game():
    global grid, slots, score, game_over, game_won, item_count, undo_count, shuffle_count, history_stack

    # 重置游戏状态
    slots = []
    score = 0
    game_over = False
    game_won = False
    item_count = 1
    undo_count = 3
    shuffle_count = 2
    history_stack = []

    # 重新初始化卡片堆
    grid = []
    for row in range(GRID_ROWS):
        grid_row = []
        for col in range(GRID_COLS):
            layers = random.randint(3, 7)
            max_card_type = len(card_images) - 1 if card_images else len(COLORS) - 1
            stack = [random.randint(0, max_card_type) for _ in range(layers)]
            stack += [stack[-1]] * (3 - layers % 3) if layers % 3 != 0 else []
            grid_row.append(stack)
        grid.append(grid_row)

    # 创建重新开始效果
    for row in range(GRID_ROWS):
        for col in range(GRID_COLS):
            x = GRID_LEFT + col * (CARD_WIDTH + SPACING) + CARD_WIDTH // 2
            y = GRID_TOP + row * (CARD_HEIGHT + SPACING) + CARD_HEIGHT // 2
            create_particles(x, y, 20)


class MovingCard:
    def __init__(self, card_type, start_x, start_y, end_x, end_y):
        self.card_type = card_type
        self.x = start_x
        self.y = start_y
        self.end_x = end_x
        self.end_y = end_y
        self.speed = 8
        self.scale = 1.5  # 点击后更大的放大比例
        self.target_scale = 1.0  # 移动过程中不小于原始尺寸
        self.scale_speed = 0.01  # 减小缩放速度

    def update(self):
        if self.x != self.end_x:
            if self.x < self.end_x:
                self.x = min(self.x + self.speed, self.end_x)
            else:
                self.x = max(self.x - self.speed, self.end_x)
        if self.y != self.end_y:
            if self.y < self.end_y:
                self.y = min(self.y + self.speed, self.end_y)
            else:
                self.y = max(self.y - self.speed, self.end_y)

        if self.scale > self.target_scale:
            self.scale = max(self.scale - self.scale_speed, self.target_scale)

        return self.x == self.end_x and self.y == self.end_y

    def draw(self):
        if card_images:
            scaled_img = pygame.transform.scale(card_images[self.card_type],
                                                (int(CARD_WIDTH * self.scale), int(CARD_HEIGHT * self.scale)))
            screen.blit(scaled_img, (self.x - (scaled_img.get_width() - CARD_WIDTH) // 2,
                                     self.y - (scaled_img.get_height() - CARD_HEIGHT) // 2))
        else:
            scaled_width = int(CARD_WIDTH * self.scale)
            scaled_height = int(CARD_HEIGHT * self.scale)
            pygame.draw.rect(screen, COLORS[self.card_type],
                             (self.x - (scaled_width - CARD_WIDTH) // 2, self.y - (scaled_height - CARD_HEIGHT) // 2,
                              scaled_width, scaled_height))


def check_victory():
    """检查是否胜利"""
    for row in grid:
        for stack in row:
            if len(stack) > 0:
                return False
    return len(slots) == 0


def create_particles(x, y, count=30):
    """在指定位置创建粒子效果"""
    for _ in range(count):
        particles.append(Particle(x, y))


# 新增：洗牌功能实现
def shuffle_grid():
    """重新排列当前卡片，但保持每种卡片类型的数量不变"""
    global grid

    # 收集所有卡片
    all_cards = []
    for row in grid:
        for stack in row:
            all_cards.extend(stack)

    # 随机打乱卡片顺序
    random.shuffle(all_cards)

    # 重新分配卡片到网格
    index = 0
    for row in range(GRID_ROWS):
        for col in range(GRID_COLS):
            layers = len(grid[row][col])
            grid[row][col] = all_cards[index:index + layers]
            index += layers

    # 创建洗牌效果
    for row in range(GRID_ROWS):
        for col in range(GRID_COLS):
            x = GRID_LEFT + col * (CARD_WIDTH + SPACING) + CARD_WIDTH // 2
            y = GRID_TOP + row * (CARD_HEIGHT + SPACING) + CARD_HEIGHT // 2
            create_particles(x, y, 15)


# 初始化卡片堆
grid = []
for row in range(GRID_ROWS):
    grid_row = []
    for col in range(GRID_COLS):
        layers = random.randint(3, 7)
        max_card_type = len(card_images) - 1 if card_images else len(COLORS) - 1
        stack = [random.randint(0, max_card_type) for _ in range(layers)]
        stack += [stack[-1]] * (3 - layers % 3) if layers % 3 != 0 else []
        grid_row.append(stack)
    grid.append(grid_row)

# 保存初始状态
initial_grid = copy.deepcopy(grid)
initial_slots = copy.copy(slots)
initial_score = score

# 主循环
clock = pygame.time.Clock()
running = True

while running:
    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            x, y = pygame.mouse.get_pos()

            # 新增：检查是否点击重新开始按钮
            if game_over and RESTART_LEFT <= x <= RESTART_LEFT + RESTART_WIDTH and RESTART_TOP <= y <= RESTART_TOP + RESTART_HEIGHT:
                restart_game()
                continue

            if not game_over:
                # 新增：检查是否点击撤销按钮
                if UNDO_LEFT <= x <= UNDO_LEFT + UNDO_WIDTH and UNDO_TOP <= y <= UNDO_TOP + UNDO_HEIGHT:
                    if undo_count > 0 and history_stack:
                        # 恢复上一步状态
                        prev_state = history_stack.pop()
                        grid, slots, score = prev_state
                        undo_count -= 1
                        # 创建撤销效果
                        for row in range(GRID_ROWS):
                            for col in range(GRID_COLS):
                                x = GRID_LEFT + col * (CARD_WIDTH + SPACING) + CARD_WIDTH // 2
                                y = GRID_TOP + row * (CARD_HEIGHT + SPACING) + CARD_HEIGHT // 2
                                create_particles(x, y, 10)

                # 新增：检查是否点击洗牌按钮
                elif SHUFFLE_LEFT <= x <= SHUFFLE_LEFT + SHUFFLE_WIDTH and SHUFFLE_TOP <= y <= SHUFFLE_TOP + SHUFFLE_HEIGHT:
                    if shuffle_count > 0:
                        # 保存当前状态到历史记录
                        history_stack.append((copy.deepcopy(grid), copy.copy(slots), score))

                        # 执行洗牌
                        shuffle_grid()
                        shuffle_count -= 1

                # 检查是否点击道具
                elif ITEM_LEFT <= x <= ITEM_LEFT + ITEM_WIDTH and ITEM_TOP <= y <= ITEM_TOP + ITEM_HEIGHT:
                    if item_count > 0:
                        # 保存当前状态到历史记录
                        history_stack.append((copy.deepcopy(grid), copy.copy(slots), score))

                        slots = []
                        item_count -= 1
                else:
                    # 计算点击位置
                    grid_col = (x - GRID_LEFT) // (CARD_WIDTH + SPACING)
                    grid_row = (y - GRID_TOP) // (CARD_HEIGHT + SPACING)
                    # 检查点击范围
                    if 0 <= grid_row < GRID_ROWS and 0 <= grid_col < GRID_COLS:
                        if len(grid[grid_row][grid_col]) > 0:
                            # 检查槽位是否已满（改为7块）
                            if len(slots) >= SLOT_COLS:
                                game_over = True
                                continue

                            # 保存当前状态到历史记录
                            history_stack.append((copy.deepcopy(grid), copy.copy(slots), score))

                            # 取出顶层卡片
                            card = grid[grid_row][grid_col].pop()
                            start_x = GRID_LEFT + grid_col * (CARD_WIDTH + SPACING)
                            start_y = GRID_TOP + grid_row * (CARD_HEIGHT + SPACING) + (
                                len(grid[grid_row][grid_col])) * (
                                              CARD_HEIGHT // 12)
                            end_x = SLOT_LEFT + len(slots) * (CARD_WIDTH + 5)
                            end_y = SLOT_TOP
                            moving_cards.append(MovingCard(card, start_x, start_y, end_x, end_y))

    # 检查是否需要切换背景
    current_time = pygame.time.get_ticks()
    if current_time - last_switch_time > BACKGROUND_SWITCH_INTERVAL:
        current_background = 1 - current_background
        last_switch_time = current_time

    # 绘制界面
    if background_img1 and background_img2:
        if current_background == 0:
            screen.blit(background_img1, (0, 0))
        else:
            screen.blit(background_img2, (0, 0))
    else:
        screen.fill(BG_COLOR)

    # 绘制卡片堆
    for row in range(GRID_ROWS):
        for col in range(GRID_COLS):
            x = GRID_LEFT + col * (CARD_WIDTH + SPACING)
            y = GRID_TOP + row * (CARD_HEIGHT + SPACING)
            stack = grid[row][col]
            for index, card_type in enumerate(stack):
                offset_y = index * (CARD_HEIGHT // 12)  # 调整重叠的偏移量
                draw_y = y + offset_y
                if card_images:
                    screen.blit(card_images[card_type], (x, draw_y))
                else:
                    pygame.draw.rect(screen, COLORS[card_type], (x, draw_y, CARD_WIDTH, CARD_HEIGHT))
                # 除了最上层卡片，其他卡片上方叠加mask图像
                if index < len(stack) - 1 and mask_img:
                    screen.blit(mask_img, (x, draw_y))

    # 绘制槽位背景
    if slot_bg_img:
        screen.blit(slot_bg_img, (SLOT_LEFT - 10, SLOT_TOP - 10))
    else:
        pygame.draw.rect(screen, (200, 200, 200),
                         (SLOT_LEFT - 5, SLOT_TOP - 5,
                          slot_width + 10, SLOT_HEIGHT + 10),
                         border_radius=10)

    # 更新并绘制移动中的卡片
    finished_cards = []
    for card in moving_cards:
        if card.update():
            finished_cards.append(card)
            slots.append(card.card_type)
        card.draw()

    # 移除已完成移动的卡片
    for card in finished_cards:
        moving_cards.remove(card)

    # 绘制槽位中已静止的卡片
    for i, card in enumerate(slots):
        x = SLOT_LEFT + i * (CARD_WIDTH + 5)
        if card_images:
            screen.blit(card_images[card], (x, SLOT_TOP))
        else:
            pygame.draw.rect(screen, COLORS[card], (x, SLOT_TOP, CARD_WIDTH, CARD_HEIGHT))

    # 绘制道具
    if item_img:
        screen.blit(item_img, (ITEM_LEFT, ITEM_TOP))
        font = pygame.font.Font(None, 24)
        text = font.render(f"x{item_count}", True, (255, 0, 0))
        screen.blit(text, (ITEM_LEFT + ITEM_WIDTH + 5, ITEM_TOP + ITEM_HEIGHT // 2 - 10))

    # 新增：绘制撤销按钮
    if undo_img:
        screen.blit(undo_img, (UNDO_LEFT, UNDO_TOP))
        font = pygame.font.Font(None, 24)
        text = font.render(f"x{undo_count}", True, (255, 0, 0))
        screen.blit(text, (UNDO_LEFT + UNDO_WIDTH + 5, UNDO_TOP + UNDO_HEIGHT // 2 - 10))

    # 新增：绘制洗牌按钮
    if shuffle_img:
        screen.blit(shuffle_img, (SHUFFLE_LEFT, SHUFFLE_TOP))
        font = pygame.font.Font(None, 24)
        text = font.render(f"x{shuffle_count}", True, (255, 0, 0))
        screen.blit(text, (SHUFFLE_LEFT + SHUFFLE_WIDTH + 5, SHUFFLE_TOP + SHUFFLE_HEIGHT // 2 - 10))

    # 绘制状态信息
    font = pygame.font.Font(None, 36)
    text = font.render(f"Score: {score}", True, (0, 0, 0))
    screen.blit(text, (20, 20))

    # 绘制槽位容量提示
    capacity_text = font.render(f"{len(slots)}/{SLOT_COLS}", True, (100, 100, 100))
    screen.blit(capacity_text, (SCREEN_WIDTH - 60, 20))

    # 检查连续三个相同卡片
    elimination_occurred = False
    if len(slots) >= 3 and slots[-1] == slots[-2] == slots[-3]:
        # 获取消除位置的中心坐标
        center_x = SLOT_LEFT + (len(slots) - 2) * (CARD_WIDTH + 5) + CARD_WIDTH // 2
        center_y = SLOT_TOP + CARD_HEIGHT // 2

        # 创建粒子效果
        create_particles(center_x, center_y, 50)

        del slots[-3:]
        score += 1
        elimination_occurred = True

    # 更新并绘制粒子
    active_particles = []
    for particle in particles:
        if particle.update():
            particle.draw()
            active_particles.append(particle)
    particles = active_particles

    # 再次检查槽位是否已满
    if len(slots) >= SLOT_COLS:
        game_over = True

    # 检查胜利条件
    if check_victory():
        game_won = True
        game_over = True

    # 新增：绘制重新开始按钮
    if game_over:
        font = pygame.font.Font(None, 36)
        text = font.render("YOU WIN!" if game_won else "GAME OVER!",
                           True, (0, 255, 0) if game_won else (255, 0, 0))
        screen.blit(text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT // 2 - 20))

        # 检查鼠标是否悬停在按钮上
        mouse_x, mouse_y = pygame.mouse.get_pos()
        is_hovering = RESTART_LEFT <= mouse_x <= RESTART_LEFT + RESTART_WIDTH and RESTART_TOP <= mouse_y <= RESTART_TOP + RESTART_HEIGHT

        # 绘制重新开始按钮
        button_color = BUTTON_HOVER_COLOR if is_hovering else BUTTON_COLOR
        pygame.draw.rect(screen, button_color,
                         (RESTART_LEFT, RESTART_TOP, RESTART_WIDTH, RESTART_HEIGHT),
                         border_radius=10)

        # 绘制按钮文字
        button_font = pygame.font.Font(None, 30)
        button_text = button_font.render("RESTART", True, TEXT_COLOR)
        screen.blit(button_text, (RESTART_LEFT + RESTART_WIDTH // 2 - button_text.get_width() // 2,
                                  RESTART_TOP + RESTART_HEIGHT // 2 - button_text.get_height() // 2))

    pygame.display.flip()
    clock.tick(30)

pygame.quit()